import utils, { NameSpace } from 'utils';
import exceed from 'utils/apimap';
import { ENUM } from 'utils/constants.js';
import { Message } from '@teamix/ui';
import { updatePageInfo } from 'pages/index/actions';
import { getTotalComments, trackViewFileAtAccept } from '../pages/changes/actions';
import intl from '../../../../../../../locale';

const ns = NameSpace('projectMergeRequestDetail');
export const RECEIVE_CRDETAIL = ns('RECEIVE_CRDETAIL');
export const RECEIVE_CHANGE_REQUEST = ns('RECEIVE_CHANGE_REQUEST');
export const RECEIVE_SUMMARY_LOGS = ns('RECEIVE_SUMMARY_LOGS');
export const RECEIVE_APPROVE_STATUS = ns('RECEIVE_APPROVE_STATUS');
export const RECEIVE_COMMIT_HISTORY = ns('RECEIVE_COMMIT_HISTORY');
export const DELETE_SOURCE_BRANCH = ns('DELETE_SOURCE_BRANCH');
export const RECEIVE_TITLE = ns('RECEIVE_TITLE');
export const RECEIVE_MERGE_DATA = ns('RECEIVE_MERGE_DATA');
export const RECEIVE_MERGE_BUILDS = ns('RECEIVE_MERGE_BUILDS');
export const RECEIVE_MERGE_ISSUES = ns('RECEIVE_MERGE_ISSUES');
export const RECEIVE_MERGE_ISSUE_DETAILS = ns('RECEIVE_MERGE_ISSUE_DETAILS');
export const CHANGE_MR_TAB_KEY = ns('CHANGE_MR_TAB_KEY');
export const UPDATE_PAGE_INFO = ns('UPDATE_PAGE_INFO');
export const UPDATE_DATA = ns('UPDATE_DATA');
export const RECEIVE_TARGET_BRANCH_SETTING = ns('RECEIVE_TARGET_BRANCH_SETTING');
export const SET_PROJECT_CLONE_DOWNLOAD = ns('SET_PROJECT_CLONE_DOWNLOAD');

const { pathResource, organization } = window.FORCE;

export function changeMrTabKey(data) {
  return (dispatch) => {
    dispatch({
      type: CHANGE_MR_TAB_KEY,
      data,
    });
  };
}

export function updateData(data) {
  return (dispatch) => {
    dispatch({
      type: UPDATE_DATA,
      data,
    });
  };
}

// 获取cr详情
export function getCrDetail(cb) {
  return (dispatch, getState) => {
    const state = getState().project.projectMergeRequestDetail.root;
    const { codeReviewDetail } = state;
    exceed
      .forceFetch({
        api: 'project.mr.get',
        params: {
          projectId: pathResource.id,
          mrId: codeReviewDetail.id,
        },

        data: {
          include_refs_ahead_behind: false,
        },
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_CRDETAIL,
          data: result,
        });

        cb && cb();

        // state: locked 表示合并中状态，轮询评审详情口，当state不是locked时，结束轮询，根据state展示对应的东西
        if (result.state === 'locked') {
          setTimeout(() => {
            dispatch(getCrDetail());
          }, 1000);
        }

        if (result.state === 'merged') {
          dispatch(getSummaryLogs());
        }
      });
  };
}

// 获取ahead、behind、support_merge_ff_only信息
export function getCrOtherInfo(cb) {
  return (dispatch, getState) => {
    const state = getState().project.projectMergeRequestDetail.root;
    const { codeReviewDetail } = state;
    exceed
      .fetch({
        api: 'project.mr.ahead_behind',
        params: {
          repoId: pathResource.id,
          // mrId: codeReviewDetail.id,
        },
        data: {
          source_branch: codeReviewDetail.source_branch || codeReviewDetail.sourceBranch,
          target_branch: codeReviewDetail.target_branch || codeReviewDetail.targetBranch,
        },
      })
      .then((result) => {
        updateData({
          mr_ahead_behind_info: result,
        })(dispatch);
        cb && cb();
      })
      .fail(() => {
        cb && cb();
      });
  };
}

// 查询评审关联的变更
export function getChangeRequest() {
  return (dispatch, getState) => {
    const state = getState().project.projectMergeRequestDetail.root;
    const { codeReviewDetail } = state;
    exceed
      .forceFetch({
        api: 'project.mr.get_cr',
        params: {
          projectId: pathResource.id,
          mrId: codeReviewDetail.id,
        },
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_CHANGE_REQUEST,
          data: result.list,
        });
      });
  };
}

// 获取commit提交历史
export function getCommitsHistory() {
  return (dispatch, getState) => {
    const state = getState().project.projectMergeRequestDetail.root;
    const { codeReviewDetail } = state;
    exceed
      .forceFetch({
        api: 'project.mr.commits.all',
        params: {
          projectId: pathResource.id,
          mrId: codeReviewDetail.id,
        },
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_COMMIT_HISTORY,
          data: result.list,
        });
      });
  };
}

export function receiveCommitHistory(list) {
  return (dispatch) => {
    dispatch({
      type: RECEIVE_COMMIT_HISTORY,
      data: list,
    });
  };
}

// 修改cr
export function modifyCr(params, cb) {
  return (dispatch, getState) => {
    const state = getState().project.projectMergeRequestDetail.root;
    const { codeReviewDetail } = state;
    if (params.assignee_id) {
      params.assignee_id = params.assignee_id.join(',');
    }
    exceed
      .forceFetch({
        api: 'project.mr.put',
        params: {
          projectId: pathResource.id,
          mrId: codeReviewDetail.id,
        },

        data: params,
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_CRDETAIL,
          data: result,
        });

        // 重新获取我的同意状态
        dispatch(getApproveStatus());

        // 重新获取详情
        dispatch(getCrDetail());

        // 重新请求日志
        dispatch(getSummaryLogs());

        cb && cb();
      });
  };
}

// 仅评审通过（不合并）
export function doAccept(cb) {
  return (dispatch, getState) => {
    const state = getState().project.projectMergeRequestDetail.root;
    const { codeReviewDetail, commitHistory } = state;

    // 取最近一次 commit 的sha，源分支版本参数，用来校验评审人打开页面后，源分支是否有了新的更新
    let lastCommit;
    if (commitHistory && commitHistory.length) {
      lastCommit = commitHistory[commitHistory.length - 1];
    }

    // accept 接口仅通过，最终把状态置为 accepted（评审通过且已合并）
    exceed
      .fetch({
        api: 'project.mr.accept',
        params: {
          projectId: pathResource.id,
          mrId: codeReviewDetail.id,
        },

        data: {
          source_branch_revision: lastCommit ? lastCommit.sha || lastCommit.id : null,
        },
      })
      .then(() => {
        // 重新获取我的同意状态
        dispatch(getApproveStatus());

        // 重新获取详情
        dispatch(getCrDetail());

        // 重新请求日志
        dispatch(getSummaryLogs());
        // 点击通过，也标记浏览结束
        dispatch(trackViewFileAtAccept());
      })
      .fail(() => {
        // 仅失败时触发回调将按钮置为非loading状态，因为成功后原按钮会消失
        cb && cb();
      });
  };
}

// 合并
export function doMerge(
  { merge_commit_message, merge_type, should_remove_source_branch = false },
  cb,
) {
  return (dispatch, getState) => {
    const state = getState().project.projectMergeRequestDetail.root;
    const { codeReviewDetail, commitHistory } = state;

    // 取最近一次 commit 的sha，源分支版本参数，用来校验评审人打开页面后，源分支是否有了新的更新
    let lastCommit;
    if (commitHistory && commitHistory.length) {
      lastCommit = commitHistory[commitHistory.length - 1];
    }
    updateData({
      isMerging: true,
    })(dispatch);

    // doMergeAsync 接口会进行异步合并，最终把状态置为 merged（评审通过且已合并）
    exceed
      .fetch({
        api: 'project.mr.doMergeSync',
        params: {
          projectId: pathResource.id,
          mrId: codeReviewDetail.id,
        },

        data: {
          source_branch_revision: lastCommit ? lastCommit.sha || lastCommit.id : null,
          should_remove_source_branch,
          merge_commit_message,
          merge_type,
        },
      })
      .then(() => {
        Message.success({
          title: intl.get({
            id: 'code-assets.projectMergeRequestDetail.actions.MergedSuccessfully',
            defaultMessage: '合并成功',
          }),
        });

        if (should_remove_source_branch) {
          dispatch({
            type: DELETE_SOURCE_BRANCH,
          });
        }

        // 重新获取详情
        dispatch(getCrDetail());
        cb && cb();
        // 更新tab上合并数量
        dispatch(updatePageInfo(window.location.pathname));
        updateData({
          isMerging: false,
        })(dispatch);
      })
      .fail(() => {
        updateData({
          isMerging: false,
        })(dispatch);
      });
  };
}

// 获取mr请求动态
export function getSummaryLogs(page) {
  return (dispatch, getState) => {
    const state = getState().project.projectMergeRequestDetail.root;
    const { codeReviewDetail } = state;
    exceed
      .forceFetch({
        // api: 'project.mr.logs.dynamics',
        api: 'project.mr.logs.summary',
        params: {
          projectId: pathResource.id,
          mrId: codeReviewDetail.id,
        },

        data: {
          page,
          per_page: 100,
        },
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_SUMMARY_LOGS,
          data: Object.assign(result, {
            currentPage: page,
          }),
        });
      });
  };
}

// 获取某个人的评审状态（新接口，用于替换上面的接口，详见：https://aone.alibaba-inc.com/project/774136/task/17013830）
export function getApproveStatus() {
  return (dispatch, getState) => {
    const state = getState().project.projectMergeRequestDetail.root;
    const { codeReviewDetail } = state;
    exceed
      .forceFetch({
        api: 'project.mr.approve_status',
        params: {
          projectId: pathResource.id,
          mrId: codeReviewDetail.id,
        },
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_APPROVE_STATUS,
          data: result,
        });
      });
  };
}

export function getTargetBranchSetting() {
  return (dispatch, getState) => {
    const state = getState().project.projectMergeRequestDetail.root;
    const { codeReviewDetail } = state;
    exceed
      .forceFetch({
        api: 'projects.branches.protected',
        params: {
          projectId: pathResource.id,
          branch: codeReviewDetail.targetBranch,
        },
      })
      .then((result) => {
        let data = result;
        if (JSON.stringify(result) === '{}') {
          data = null;
        }
        dispatch({
          type: RECEIVE_TARGET_BRANCH_SETTING,
          data,
        });
      });
  };
}

// 删除分支接口
export function deleteSourceBranch() {
  return (dispatch, getState) => {
    const state = getState().project.projectMergeRequestDetail.root;
    const { codeReviewDetail } = state;
    exceed
      .fetch({
        api: 'project.branches.delete',
        params: {
          projectId: pathResource.id,
          branch: utils.revisionEncodeURI(codeReviewDetail.source_branch),
        },
      })
      .then(() => {
        Message.success({
          title: intl.get({
            id: 'code-assets.projectMergeRequestDetail.actions.Deleted',
            defaultMessage: '删除成功',
          }),
        });

        dispatch({
          type: DELETE_SOURCE_BRANCH,
        });

        // 重新获取详情
        dispatch(getCrDetail());

        // 重新请求日志
        dispatch(getSummaryLogs());
        // 获取最新的分支状态 https://work.aone.alibaba-inc.com/issue/30661592
        dispatch(updatePageInfo(window.location.pathname));
      })
      .fail(console.log);
  };
}

// 查询数据
export function getMergeRequest() {
  return (dispatch) => {
    exceed
      .forceFetch({
        api: 'project.settings.merge_requests.get',
        params: {
          id: pathResource.id,
        },
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_MERGE_DATA,
          data: result,
        });

        // cb(result);
      });
  };
}

// 卡点
export function getBuilds() {
  return (dispatch, getState) => {
    const state = getState().project.projectMergeRequestDetail.root;
    const { codeReviewDetail, mergeRequestBuilds } = state;
    exceed
      .fetch({
        api: 'project.mr.builds',
        params: {
          mrId: codeReviewDetail.id,
          projectId: pathResource.id,
        },
      })
      .then((result) => {
        const data = result.slice(1);
        dispatch({
          type: RECEIVE_MERGE_BUILDS,
          data,
        });

        dispatch(getAllIssues(data));
        const preRunning = mergeRequestBuilds.some((item) => {
          return item.state === 'RUNNING';
        });
        const curRunning = data.some((item) => {
          return item.state === 'RUNNING';
        });
        if (preRunning && !curRunning) {
          dispatch(getSummaryLogs());
          dispatch(getTotalComments());
          dispatch(getCrDetail());
        }
      })
      .fail((err) => {
        console.error(err);
      });
  };
}
// 卡点issues
export function getAllIssues(builds) {
  // 未执行的卡点没有buildId，使用filter过滤掉
  const codeBuilds = builds.filter((item) => ENUM.buildInTaskNames.includes(item.enTaskName));
  return (dispatch) => {
    const promises = codeBuilds.map((item) => {
      return getIssuesById({
        projectId: pathResource.id,
        buildId: item.id,
      });
    });
    Promise.all(promises)
      .then((results) => {
        let allIssues = [];
        results.forEach((item) => {
          allIssues = allIssues.concat(item);
        });
        dispatch({
          type: RECEIVE_MERGE_ISSUES,
          data: allIssues,
        });

        // 根据build ID 和issue list查询详情
        const newAllPromises = codeBuilds.map((item, index) => {
          const curBuildIssues = results[index];
          let issue_id_list = [];
          // 获取当前buildId下issue列表ID
          curBuildIssues.forEach((issue) => {
            issue_id_list = [...issue_id_list, ...issue.issue_id_list];
          });

          const params = {
            buildId: item.id,
            issue_ids: issue_id_list.join() || '',
          };

          return getIssuesDetails(params);
        });

        const detailPromises = [];
        newAllPromises.forEach((promiseArr) => {
          Array.isArray(promiseArr) && detailPromises.push(...promiseArr);
        });
        return Promise.all(detailPromises);
      })
      .then((details) => {
        const newDetails = [];
        details.forEach((detail) => {
          Array.isArray(detail) && newDetails.push(...detail);
        });
        dispatch({
          type: RECEIVE_MERGE_ISSUE_DETAILS,
          data: newDetails,
        });
      })
      .catch((err) => {
        console.error(err);
      });
  };
}

// 单个详情接口
function getSingleDetail({ issue_ids, buildId }) {
  return new Promise((resolve) => {
    exceed
      .fetch({
        api: 'projects.builds.issues.batch',
        params: { projectId: pathResource.id, buildId },
        data: {
          issue_ids,
        },
      })
      .then((result) => {
        const data = result.slice(1);
        resolve(data);
      })
      .fail(() => {
        resolve([]);
      });
  });
}

//

// 获取所有的issues内容
export function getIssuesDetails({ buildId, issue_ids }) {
  const issue_ids_arr = issue_ids.split(',');
  const issue_id_length = issue_ids_arr.length;

  const list_of_issue_ids = [];
  let batch_size;

  const promises = [];

  if (issue_id_length > 50) {
    // issue大于50分批查询
    batch_size = Math.ceil(issue_id_length / 50);
    for (let i = 0; i < batch_size; i++) {
      list_of_issue_ids[i] = issue_ids_arr.slice(50 * i, Math.min(50 * (i + 1), issue_id_length));
    }

    for (let i = 0; i < batch_size; i++) {
      const ids = list_of_issue_ids[i].join(',');

      const curPromise = getSingleDetail({ buildId, issue_ids: ids });
      promises.push(curPromise);
    }
  } else {
    const curPromise = getSingleDetail({ buildId, issue_ids });
    promises.push(curPromise);
  }
  return promises;
}

// 根据获取issue列表
function getIssuesById({ buildId, projectId }) {
  return new Promise((resolve, reject) => {
    exceed
      .fetch({
        api: 'projects.builds.issues',
        params: { projectId, buildId },
      })
      .then((result) => {
        const data = result.slice(1);
        resolve(data);
      })
      .fail((err) => {
        reject(err);
      });
  });
}

// 获取mr评论配置
export function getMrCommentConfig() {
  return (dispatch) => {
    exceed
      .fetch({
        api: 'merge_request.comment.config',
      })
      .then((result) => {
        updateData({
          mrCommentConfig: result,
        })(dispatch);
      })
      .fail(console.error);
  };
}

export function getIpWhiteList() {
  return (dispatch) => {
    exceed
      .forceFetch({
        api: 'organization.ip_setting',
        params: {
          id: organization.id,
        },
      })
      .then((result) => {
        updateData({
          ipSetting: result,
        })(dispatch);
      });
  };
}

export function getCloneDownloadSetting() {
  return (dispatch) => {
    exceed
      .forceFetch({
        api: 'project.clone_download',
        params: {
          projectId: pathResource.id,
        },
      })
      .then((result) => {
        dispatch({
          type: SET_PROJECT_CLONE_DOWNLOAD,
          data: result,
        });
      });
  };
}
